package com.qhgrain.app.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.paas.base.modules.utils.lang.StringUtil;
import com.paas.base.modules.utils.page.PageBean;
import com.qhgrain.app.constant.UrlEnum;
import com.qhgrain.app.service.ApplicationService;
import com.qhgrain.app.service.MenuService;
import com.qhgrain.app.service.PermissionService;
import com.qhgrain.app.service.RoleService;
import com.qhgrain.app.service.SyncTo4AService;
import com.qhgrain.app.service.UnitService;
import com.qhgrain.app.service.UserService;
import com.qhgrain.app.util.ConfigUtil;
import com.qhgrain.app.util.MenuTreeUtil;
import com.qhgrain.app.vo.AppVo;
import com.qhgrain.app.vo.MenuVo;
import com.qhgrain.app.vo.PairVo;
import com.qhgrain.app.vo.PermissionVo;
import com.qhgrain.app.vo.RoleUnitVo;
import com.qhgrain.app.vo.RoleVo;
import com.qhgrain.app.vo.Unit;
import com.qhgrain.app.vo.UnitVo;
import com.qhgrain.app.vo.UserVo;
import com.qhgrain.gway.util.HttpUtil;

@Controller
@RequestMapping("/role")
public class RoleController {

	private static Logger LOG = LoggerFactory.getLogger(RoleController.class);
	
	static String serverUrl = ConfigUtil.getProperties(UrlEnum.MENU_ROLE_PERMISSION)+"/role";
	
	@Autowired
	private ApplicationService applicationService;
	@Autowired
	private PermissionService permissionService;
	@Autowired
	private MenuService menuService;
	@Autowired
	private RoleService roleService;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private UnitService unitService;
	
	@Autowired
	private SyncTo4AService syncTo4AService;
	
	@RequestMapping(value="/list")
	public String queryRoles(Model model){
		List<PairVo> roleTypeList = this.roleService.getRoleAllType();
		model.addAttribute("roleTypeList",roleTypeList);
		return "role/role_list";
	}
	
	@RequestMapping(value="/list/table")
	public String queryRolesForTable(Model model,String pageNo,String pageSize,String roleName,String roleType){
		if(StringUtils.isEmpty(pageNo)){
			pageNo="1";
		}
		if(StringUtil.isBlank(pageSize)){
			pageSize = "10";
		}
		Map<String,Object> map = new HashMap<String,Object>();
		if(StringUtil.isNotBlank(roleName)){
			map.put("roleName", roleName.trim());
			model.addAttribute("roleName", roleName.trim());
		}
		if(StringUtil.isNotBlank(roleType)){
			map.put("roleType", roleType.trim());
			model.addAttribute("roleType", roleType.trim());
		}
		map.put("page", pageNo);
		map.put("pageSize", pageSize);
		
		String requestVo;
		PageBean<Object> pageBean = new PageBean<Object>(Integer.parseInt(pageNo),Integer.parseInt(pageSize));;
		List<PairVo> roleTypeList = this.roleService.getRoleAllType();
		try {
			requestVo = HttpUtil.postFormParams(serverUrl, "/query/page", map);
			JSONObject voJson = JSONObject.parseObject(requestVo);
			
			
			if("1".equals(voJson.getString("state"))){
				JSONObject dataJson = voJson.getJSONObject("data");
				int count = dataJson.getIntValue("totalCount");
				JSONArray list = dataJson.getJSONArray("list");
				for(int i=0;i<list.size();i++){
					findRoleTypeName(roleTypeList,list.getJSONObject(i));
				}
				pageBean.setData(list);
				pageBean.setTotalCount(count);
				
				
			}else{
				LOG.error("角色查询,api出错。。。。"+requestVo);
			}
		
		} catch (IOException e) {
			LOG.error("角色查询出错。。。。",e);
		}

		model.addAttribute("pageBean", pageBean);
		model.addAttribute("roleTypeList",roleTypeList);
		return "role/role_list_table";
	}
	@RequiresPermissions({"common-service-role:delete"})
	@RequestMapping(value="/delete")
	@ResponseBody
	public JSONObject delete(Model model, String ids){
		JSONObject result = new JSONObject();
		if(StringUtil.isBlank(ids)){
			result.put("code", "0");
			result.put("msg", "角色id不能为空");
		}else{
			
			try {
				Map<String,Object> paramMap = new HashMap<String,Object>();
				paramMap.put("ids", ids);
				
				//查询出要删除的角色用于写日志
				String[] idArray = ids.split(",");
				List<RoleVo> roleVoList = new ArrayList<RoleVo>();
				String url = serverUrl+"/get/role/";
				for(String id:idArray){
					url += id;
					try {
						String vo = HttpUtil.get(url);
						System.out.println(vo);//
						JSONObject voJson = JSONObject.parseObject(vo);
						if("1".equals(voJson.getString("state"))){
							roleVoList.add(JSONObject.parseObject(voJson.getString("data"), RoleVo.class));
							System.out.println("查出要删除的role："+voJson.getString("data"));
							System.out.println("数组："+roleVoList.toString());
						}else{
							LOG.warn(id+"查询id对应的角色不存在.");
						}
					} catch (Exception e) {
						LOG.error("根据id查询角色失败，"+e.getMessage());
					}
				}
				
				String vo = HttpUtil.postFormParams(serverUrl, "/delete", paramMap);
				JSONObject voJson = JSONObject.parseObject(vo);
				if("1".equals(voJson.getString("state"))){
					result.put("code", "success");
					result.put("msg", "成功");
					//同步到4A
					this.syncTo4AService.syncDelRole(roleVoList);
					
				}else{
					result.put("code", "fail");
					result.put("msg", "系统出错，删除失败!");
					LOG.error("删除角色,api失败..."+vo);
				}
			} catch (Exception e) {
				LOG.error("删除角色，系统出错....",e);
				result.put("code", "fail");
				result.put("msg", "系统出错");
			}
		}
		
		return result;
	}
	@RequiresPermissions({"common-service-role:add"})
	@RequestMapping(value="/add")
	public String addPage(Model model){
		model.addAttribute("role", new JSONObject());
		model.addAttribute("roleTypeList", this.roleService.getRoleAllType());
		return "role/role_edit";
	}
	
	@RequiresPermissions({"common-service-role:edit"} )
	@RequestMapping(value="/edit/{roleId}")
	public String editPage(Model model,@PathVariable String roleId) throws Exception{
		RoleVo role = this.roleService.find(roleId);
		model.addAttribute("role", role);
		model.addAttribute("roleTypeList",this.roleService.getRoleAllType());
		model.addAttribute("roleUserList",this.userService.getUsersByRoleId(roleId));
		return "role/role_edit";
	}
	/**
	 * 校验roleCode的唯一性
	 * @param roleCode
	 * @return
	 */
	@RequestMapping(value="/findByRoleCode/{roleCode}")
	@ResponseBody
	public JSONObject findByRoleCode(@PathVariable String roleCode){
		JSONObject result = new JSONObject();
		try {
			if(StringUtil.isBlank(roleCode)){
				result.put("code", "fail");
				result.put("msg", "roleCode不能为空");
			}else{
				RoleVo role = this.roleService.findByRoleCode(roleCode);
				if(role != null){
					result.put("code", "1");
					result.put("msg","roleCode已存在"	);
				}else{
					result.put("code", "2");
					result.put("msg","roleCode还未存在");
				}
			}
			
		} catch (Exception e) {
			result.put("code", "fail");
			result.put("msg", "系统出错");
			LOG.error("根据roleCode校验唯一性，系统出错...",e);
		}
		return result;
	}
	
	@RequestMapping(value="/save",method=RequestMethod.POST)
	@ResponseBody
	public JSONObject save(Model model,String roleId,String roleName,String roleType,String status,String userIds,String roleCode){
		JSONObject result = new JSONObject();
		try {
			if(StringUtil.isBlank(roleName) || StringUtil.isBlank(roleType) || StringUtil.isBlank(status) || StringUtil.isBlank(roleCode)){
				result.put("code", "fail");
				result.put("msg","角色名称或类型或状态或编码不能为空");
			}else{
				String vo ;
				Map<String,Object> map = new HashMap<String,Object>();
				map.put("roleName", roleName);
				map.put("roleType", roleType);
				map.put("status", status);
				map.put("roleCode", roleCode);
				if(StringUtil.isBlank(roleId)){
					//新增
					vo = HttpUtil.postFormParams(serverUrl, "/add", map);
					
				}else{
					//修改
					map.put("roleId", roleId);
					vo = HttpUtil.postFormParams(serverUrl, "/edit", map);
				}
				JSONObject voJson = JSONObject.parseObject(vo);
				if("1".equals(voJson.getString("state"))){
					//同步到4A
					if(StringUtil.isBlank(roleId)){
						this.syncTo4AService.syncAddRole(voJson.getString("data"), roleName, roleCode, roleType);
					}else{
						this.syncTo4AService.syncUpdateRole(roleId, roleName, roleCode, roleType);
					}
					
					if(StringUtil.isBlank(roleId)){
						roleId = voJson.getString("data");
					}
					//维护角色-用户间的关联
					List<String> userIdList = null;
					if(StringUtil.isNotBlank(userIds)){
						userIdList = new ArrayList<String>();
						List<String> list  = Arrays.asList(userIds.split(","));
						//去重复
						for(String s : list){
							if(!userIdList.contains(s)){
								userIdList.add(s);
							}
						}
					}
					this.roleService.saveRoleUsers(roleId, userIdList);
					result.put("code", "success");
					result.put("msg", "成功");
					
				}else{
					result.put("code", "fail");
					result.put("msg", "系统出错，操作失败!");
					LOG.error("保存角色,api失败..."+vo);
				}
			}
		} catch (Exception e) {
			LOG.error("保存角色系统出错。。。",e);
		}
		return result;
	}
	
	
	
	private void findRoleTypeName(List<PairVo> roleTypeList,JSONObject roleType){
		PairVo t ;
		for(int i=0;i<roleTypeList.size();i++){
			t = roleTypeList.get(i);
			if(t.getCode().equals(roleType.getString("type"))){
				roleType.put("roleTypeName", t.getName());
				break;
			}
		}
	}
	/**
	 * 角色类型,1应用角色，2业务角色，如果是1应用角色，
	 * 则授菜单权限，如果是业务角色，则授组织机构
	 * @param model
	 * @param roleId
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value="/permission/page/{roleId}")
	public String grantPermissionPage(Model model,@PathVariable("roleId")String roleId) throws Exception{
		RoleVo role = this.roleService.find(roleId);
		model.addAttribute("roleId",roleId);
		//应该按用户，获取登录用户所拥有的应用，以后处理
	//	model.addAttribute("appList",applicationService.getAll(null));
		model.addAttribute("appList",applicationService.queryByRole(roleId));
		return "1".equals(role.getType())? "role/role_permission" : "role/role_unit";
		
		
	}
	/**
	 * 根据角色（应用角色）、应用获取权限（菜单权限、功能权限）
	 * @param model
	 * @param roleId
	 * @param appId
	 * @return
	 */
	@RequestMapping(value="/query/permission/detail")
	public String queryPermissionDetail(Model model ,String roleId,String appId){
		//1.获取app下的所有正常菜单
		try {
			JSONArray array = this.menuService.getAll(appId, null, "0");
			List<MenuVo> menus = JSONArray.parseArray(array.toJSONString(), MenuVo.class);
		//	System.out.println("菜单数..."+menus.size());
			if(menus.size()>0){
				List<String> menuIds = new ArrayList<String>();
				for(MenuVo m : menus){
					menuIds.add(m.getId());
				}
				//2.获取菜单的所有权限配置
				JSONArray perArray = this.permissionService.queryByMenuIds(menuIds);
				List<PermissionVo> permissions = JSONArray.parseArray(perArray.toJSONString(), PermissionVo.class);
				//3.菜单和权限进行匹配
				for(PermissionVo p : permissions){
					menuMatchPermission(p,menus);
				}
				//获取该角色拥有的权限
				List<String> rolePers = this.roleService.getPermissionsBy(roleId, appId);
				if(rolePers.size() > 0){
					for(PermissionVo p : permissions){
						roleMatchPermission(p,rolePers);
					}
				}
				//4.菜单排序
				menus = MenuTreeUtil.buildTree(menus,true,true);
				model.addAttribute("menuList", menus);
				
			}
		} catch (Exception e) {
			LOG.error("角色授权，根据api获取菜单及权限详情出错...",e);
			return null;
		}
		return "role/role_permission_detail";
	}
	
	private void menuMatchPermission(PermissionVo p ,List<MenuVo> menus){
		for(MenuVo m : menus){
			if(m.getId().equals(p.getMenuId())){
				if("0".equals(p.getType())){//菜单权限
					m.setMenuPermission(p);
				}else{
					m.setOperationPermission(p);
				}
				break;
			}
		}
	}
	
	private void roleMatchPermission(PermissionVo p,List<String> rolePers){
		for(String t: rolePers){
			if(t.equals(p.getId())){
				p.setCheckbox("1");
				break;
			}
		}
	}
	/**
	 * 各模块角色（业务），应用获取组织
	 * @param roleId
	 * @param appId
	 * @return
	 */
	@RequestMapping(value="/query/app/units")
	@ResponseBody
	public JSONObject queryAppUnits(String roleId,String appId){
		JSONObject result ;
		try {
			result = new JSONObject();
		//	List<Unit> allUnits = this.unitService.getAllUnit();
			List<Unit> allUnits = this.unitService.getUnitsForRoleGrant(appId);
			RoleUnitVo roleUnit = this.unitService.getRoleUnitByRole(roleId, appId);
			
			result.put("data",createUnitTree(allUnits,roleUnit));
			result.put("code", "success");
		} catch (Exception e) {
			result = new JSONObject();
			result.put("code", "fail");
			LOG.error("根据业务角色、应用获取组织，系统出错...",e);
		}
		
		return result;
	}
	/**
	 * 
	 * @param alls 所有的组织机构
	 * @param vo 角色-应用-拥有的组织
	 * @return
	 */
	private JSONArray createUnitTree(List<Unit> alls,RoleUnitVo vo){
		JSONArray array = new JSONArray();
		Set<String> ids = new HashSet<String>();
		if(vo != null && vo.getUnitList() != null){
			for(UnitVo v : vo.getUnitList()){
				ids.add(v.getId());
			}
		}
		
		if(alls != null && alls.size()>0){
			JSONObject o = null;
			for(Unit u : alls){
				o = new JSONObject();
				o.put("id", u.getUnitId());
				o.put("pId", u.getParentId());
				o.put("name", u.getUnitName());
				o.put("open", true);
				o.put("checked", ids.contains(u.getUnitId()));
				
				array.add(o);
			}
		}
		return array;
	}
	
	/**
	 * 保存角色-应用-菜单权限
	 * @param model
	 * @param roleId
	 * @param appId
	 * @param permissionIds
	 * @return
	 */
	@RequestMapping(value="/save/permission")
	@ResponseBody
	public JSONObject savePermission(Model model,String roleId,String appId,String permissionIds){
		JSONObject result = new JSONObject();
		try {
			//获取该角色拥有的权限
			List<String> rolePers = this.roleService.getPermissionsBy(roleId, appId);
			List<String> deleteIds = null;
			if(rolePers != null && rolePers.size() > 0){
				deleteIds = rolePers;
				
			}
			//要新增的权限
			List<String> addIds = null;
			if(StringUtil.isNotBlank(permissionIds)){
				addIds = Arrays.asList(permissionIds.split(","));
			}
			if(this.roleService.grantRolePermission(roleId, addIds, deleteIds)){
				result.put("code", "success");
			}else{
				result.put("code", "fail");
			}
		} catch (Exception e) {
			LOG.error("保存角色授权，角色-权限关联失败...",e);
			result.put("code", "fail");
		}
		
		return result;
	}
	/**
	 * 保存角色-应用-组织关联数据
	 * @param roleUnit
	 * @return
	 */
	@RequestMapping(value="/save/role/app/units")
	@ResponseBody
	public JSONObject saveRoleAppUnits(@RequestBody RoleUnitVo roleUnit){
		JSONObject result = new JSONObject();
		try {
			if(roleUnit == null || StringUtil.isBlank(roleUnit.getRoleId()) || StringUtil.isBlank(roleUnit.getAppId())){
				result.put("code", "fail");
				result.put("msg", "roleId及appId不能为空");
			}else{
				this.unitService.saveRoleUnit(roleUnit);
				result.put("code", "success");
			}
		} catch (Exception e) {
			LOG.error("保存角色授权，角色-权限关联失败...",e);
			result.put("code", "fail");
			result.put("msg", "系统错误");
		}
		
		return result;
	}
	
	@RequestMapping(value="/open/user/page")
	public String openUserPage(Model model){
		
		return "role/select_user_page";
	}
	
	@RequestMapping(value="/query/user")
	public String queryUser(Model model,String unitName,String userName,String pageNo,String pageSize) throws NumberFormatException, Exception{
		int size = StringUtil.isBlank(pageSize) ? 10 : Integer.parseInt(pageSize);
		if(StringUtil.isBlank(pageNo)){
			pageNo = "1";
		}
		PageBean<UserVo> pageBean = this.userService.queryPage(userName, null,null, unitName,null, null, "1", Integer.parseInt(pageNo), size);
		model.addAttribute("pageBean",pageBean);
		return "role/user_table_checkbox";
	}
	/**
	 * 赋应用页面
	 * @param model
	 * @param roleId
	 * @return
	 * @throws Exception 
	 */
	@RequestMapping(value="/open/app/page/{roleId}")
	public String openAppPage(Model model,@PathVariable("roleId")String roleId) throws Exception{
		//所有的应用
		List<AppVo> all = this.applicationService.getAll3(null);
		//已有的
		List<AppVo> has = this.applicationService.queryByRole(roleId);
		//从所有中把已有的剔除
		List<AppVo> noHas = new ArrayList<AppVo>();
		if(all != null && has != null && has.size() > 0){
			Set<String> set = new HashSet<String>();
			for(AppVo v : has){
				set.add(v.getId());
			}
			for(AppVo a : all){
				if(set.add(a.getId())){
					noHas.add(a);
				}
			}
		}else{
			noHas = all;
		}
		model.addAttribute("roleId",roleId);
		model.addAttribute("hasList",has);
		model.addAttribute("noHasList",noHas);
		return "role/role_application";
	}
	/**
	 * 保存角色应用关联
	 * @param roleId
	 * @param appIds
	 * @return
	 */
	@RequestMapping(value="/save/role/application")
	@ResponseBody
	public JSONObject saveRoleApplication(String roleId,String appIds){
		JSONObject result = new JSONObject();
		try {
			if(StringUtil.isBlank(roleId)){
				result.put("code", "fail");
				result.put("msg", "roleId不能为空");
			}else{
				List<String> appIdList = StringUtil.isNotBlank(appIds)?Arrays.asList(appIds.split(",")):null;
				this.applicationService.saveRoleApplication(roleId, appIdList);
				result.put("code", "success");
			}
		} catch (Exception e) {
			LOG.error("保存角色授权，角色-权限关联失败...",e);
			result.put("code", "fail");
			result.put("msg", "系统错误");
		}
		
		return result;
	}
}
